{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Data from chapter, Imbalanced Learn - Not even 1% win the lottery\n",
    "from sklearn.datasets import fetch_openml\n",
    "data = fetch_openml(data_id=1220)\n",
    "\n",
    "df = pd.DataFrame(\n",
    "    data['data'],\n",
    "    columns=data['feature_names']\n",
    ")[\n",
    "    [\n",
    "        'user_id',\n",
    "        'ad_id'\n",
    "    ]\n",
    "].astype(int)\n",
    "\n",
    "\n",
    "df['user_rating'] = pd.Series(data['target']).astype(int) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.16841894462801643"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df['user_rating'].mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>ad_id</th>\n",
       "      <th>user_rating</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>8343295</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>562934</td>\n",
       "      <td>20017077</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>11621116</td>\n",
       "      <td>21348354</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>8778348</td>\n",
       "      <td>20366086</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    user_id     ad_id  user_rating\n",
       "0         0   8343295            0\n",
       "1    562934  20017077            1\n",
       "2  11621116  21348354            0\n",
       "3   8778348  20366086            0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>ad_id</th>\n",
       "      <th>6803526</th>\n",
       "      <th>8343295</th>\n",
       "      <th>9027213</th>\n",
       "      <th>20017077</th>\n",
       "      <th>20366086</th>\n",
       "      <th>20886690</th>\n",
       "      <th>21186478</th>\n",
       "      <th>21348354</th>\n",
       "      <th>21367376</th>\n",
       "      <th>21811752</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>user_id</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>562934</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>579253</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2886008</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5277279</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7589739</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8778348</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11621116</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11808635</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12118311</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "ad_id     6803526   8343295   9027213   20017077  20366086  20886690  \\\n",
       "user_id                                                                \n",
       "0                0         0         0         0         0         0   \n",
       "562934           0         0         0         1         0         0   \n",
       "579253           0         0         0         0         0         0   \n",
       "2886008          0         0         0         0         0         0   \n",
       "5277279          0         0         0         0         0         0   \n",
       "7589739          0         0         0         0         0         0   \n",
       "8778348          0         0         0         0         0         0   \n",
       "11621116         0         0         0         0         0         0   \n",
       "11808635         0         0         1         0         0         0   \n",
       "12118311         0         0         0         0         0         0   \n",
       "\n",
       "ad_id     21186478  21348354  21367376  21811752  \n",
       "user_id                                           \n",
       "0                0         0         0         0  \n",
       "562934           0         0         0         0  \n",
       "579253           0         0         0         0  \n",
       "2886008          1         0         0         0  \n",
       "5277279          0         0         0         0  \n",
       "7589739          0         0         0         0  \n",
       "8778348          0         0         0         0  \n",
       "11621116         0         0         0         0  \n",
       "11808635         0         0         0         0  \n",
       "12118311         0         0         0         0  "
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head(10).groupby(\n",
    "    ['user_id', 'ad_id']\n",
    ").max().reset_index().pivot(\n",
    "    'user_id', 'ad_id', 'user_rating'\n",
    ").fillna(0).astype(int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.9999885602175846"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dfdf = df.groupby(\n",
    "    ['user_id', 'ad_id']\n",
    ").max().reset_index().pivot(\n",
    "    'user_id', 'ad_id', 'user_rating'\n",
    ").fillna(0).astype(int)\n",
    "\n",
    "\n",
    "(\n",
    "   dfdf == 0 \n",
    ").sum().sum() / (dfdf.shape[0] * dfdf.shape[1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Loading Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from surprise.dataset import Dataset\n",
    "from surprise import Reader\n",
    "\n",
    "reader = Reader(rating_scale=(0, 1))\n",
    "dataset = Dataset.load_from_df(df, reader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset_subset = Dataset.load_from_df(df.sample(frac=0.2, random_state=0), reader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(39948, 7990)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset.df.shape[0], dataset_subset.df.shape[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Train/Test Split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from surprise.model_selection import train_test_split\n",
    "\n",
    "trainset, testset = train_test_split(dataset, test_size=0.25)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# K-Fold Cross Validation "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from surprise.model_selection import cross_validate\n",
    "\n",
    "def predict_evaluate(recsys, dataset, name='Algorithm'):\n",
    "    scores = cross_validate(recsys, dataset, measures=['RMSE', 'MAE'], cv=4, n_jobs=-1, verbose=False)\n",
    "    print(\n",
    "        'Testset Avg. MAE: {:.2f} & Avg. RMSE: {:.2f} [{}]'.format(\n",
    "            scores['test_mae'].mean(),\n",
    "            scores['test_rmse'].mean(),\n",
    "            name\n",
    "        )\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Random Recommender"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from surprise import AlgoBase\n",
    "\n",
    "class RandomRating(AlgoBase):\n",
    "\n",
    "    def __init__(self, p=0.5):\n",
    "        self.p = p\n",
    "        AlgoBase.__init__(self)\n",
    "\n",
    "    def estimate(self, u, i):\n",
    "        return np.random.binomial(n=1, p=self.p, size=1)[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.28 & Avg. RMSE: 0.53 [RandomRating]\n"
     ]
    }
   ],
   "source": [
    "recsys = RandomRating(p=0.168)\n",
    "predict_evaluate(recsys, dataset, 'RandomRating')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# KNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.33 & Avg. RMSE: 0.47 [NormalPredictor]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.random_pred import NormalPredictor\n",
    "\n",
    "recsys = NormalPredictor()\n",
    "predict_evaluate(recsys, dataset, 'NormalPredictor')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### In case you do not have enough memory on your machine\n",
    " \n",
    "I disabled the next cell, in case you do not have enough memory on your machine.\n",
    "And added an alternative code with smaller data set below it. \n",
    "In case you have enough memory, re-enable the next cell."
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "# Run this if you have enough memory\n",
    "\n",
    "from surprise.prediction_algorithms.knns import KNNBasic\n",
    "\n",
    "recsys = KNNBasic(verbose=False)\n",
    "predict_evaluate(recsys, dataset, 'KNNBasic')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.28 & Avg. RMSE: 0.38 [KNNBasic]\n"
     ]
    }
   ],
   "source": [
    "# Run this if you do not have enough memory\n",
    "\n",
    "from surprise.prediction_algorithms.knns import KNNBasic\n",
    "\n",
    "recsys = KNNBasic(verbose=False)\n",
    "predict_evaluate(recsys, dataset_subset, 'KNNBasic')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# from surprise.prediction_algorithms.knns import KNNWithMeans\n",
    "\n",
    "# recsys = KNNWithMeans(verbose=False)\n",
    "# predict_evaluate(recsys, dataset, 'KNNWithMeans')\n",
    "\n",
    "# Gives same results\n",
    "# Testset Avg. MAE: 0.28 & Avg. RMSE: 0.38 [KNNBasic]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.29 & Avg. RMSE: 0.38 [KNNBasic]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.knns import KNNBasic\n",
    "\n",
    "sim_options = {\n",
    "    'name': 'cosine', 'user_based': False\n",
    "}\n",
    "recsys = KNNBasic(k=20, sim_options=sim_options, verbose=False)\n",
    "predict_evaluate(recsys, dataset, 'KNNBasic')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "dataset_subset = Dataset.load_from_df(df.sample(frac=0.25, random_state=0), reader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best MAE: 0.28\n",
      "Best RMSE: 0.38\n",
      "Best Params {'sim_options': {'name': 'pearson', 'user_based': True}, 'k': 20, 'verbose': True}\n"
     ]
    }
   ],
   "source": [
    "from surprise.model_selection import GridSearchCV\n",
    "from surprise.prediction_algorithms.knns import KNNBasic\n",
    "\n",
    "param_grid = {\n",
    "    'sim_options': {\n",
    "        'name':['cosine', 'pearson'],\n",
    "    },\n",
    "    'k': [5, 10, 20, 40],\n",
    "    'verbose': [True],\n",
    "}\n",
    "\n",
    "gscv = GridSearchCV(KNNBasic, param_grid, measures=['rmse', 'mae'], cv=4, n_jobs=-1)\n",
    "gscv.fit(dataset_subset)\n",
    "\n",
    "print('Best MAE:', gscv.best_score['mae'].round(2))\n",
    "print('Best RMSE:', gscv.best_score['rmse'].round(2))\n",
    "print('Best Params', gscv.best_params['rmse'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Baseline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.27 & Avg. RMSE: 0.37 [BaselineOnly]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.baseline_only import BaselineOnly\n",
    "\n",
    "recsys = BaselineOnly(verbose=False)\n",
    "predict_evaluate(recsys, dataset, 'BaselineOnly')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# SVD"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.26 & Avg. RMSE: 0.37 [SVD]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.matrix_factorization import SVD\n",
    "\n",
    "recsys = SVD()\n",
    "predict_evaluate(recsys, dataset, 'SVD')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.27 & Avg. RMSE: 0.38 [SVD]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.matrix_factorization import SVD\n",
    "\n",
    "recsys = SVD(biased=False)\n",
    "predict_evaluate(recsys, dataset, 'SVD')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.27 & Avg. RMSE: 0.38 [SVD]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.matrix_factorization import SVD\n",
    "\n",
    "recsys = SVD(n_factors=10, biased=False)\n",
    "predict_evaluate(recsys, dataset, 'SVD')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[-0.04079952,  0.22005486,  0.01300291, -0.1422041 ],\n",
       "        [ 0.14645155, -0.05769107, -0.14960378, -0.02046191],\n",
       "        [-0.0139886 ,  0.05029478,  0.01072973,  0.07891075],\n",
       "        ...,\n",
       "        [ 0.0996747 , -0.03619214, -0.09841533,  0.09995715],\n",
       "        [ 0.07826921, -0.06432168,  0.0981659 , -0.01708438],\n",
       "        [ 0.03335689,  0.01388545,  0.05406328,  0.16213233]]),\n",
       " array([[ 0.09958162, -0.15743554,  0.09750013,  0.0211318 ],\n",
       "        [ 0.23942227,  0.22177237, -0.07680189,  0.09632363],\n",
       "        [-0.01237997, -0.04369384,  0.03694891,  0.11268999],\n",
       "        ...,\n",
       "        [ 0.17394037, -0.0285541 ,  0.07133387,  0.03640401],\n",
       "        [ 0.04252783,  0.0047859 ,  0.00967947, -0.01243682],\n",
       "        [-0.04806168,  0.0150432 , -0.08181834,  0.01670878]]))"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "recsys = SVD(n_factors=4, biased=True)\n",
    "recsys.fit(trainset)\n",
    "\n",
    "recsys.pu, recsys.qi\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.27 & Avg. RMSE: 0.38 [SVD]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.matrix_factorization import SVD\n",
    "\n",
    "recsys = SVD(n_factors=2, biased=False)\n",
    "predict_evaluate(recsys, dataset, 'SVD')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.27 & Avg. RMSE: 0.37 [SVD]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.matrix_factorization import SVD\n",
    "\n",
    "recsys = SVD(n_factors=5, n_epochs=10, biased=True)\n",
    "predict_evaluate(recsys, dataset, 'SVD')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testset Avg. MAE: 0.26 & Avg. RMSE: 0.38 [SVD]\n"
     ]
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.matrix_factorization import SVD\n",
    "\n",
    "recsys = SVD(n_factors=5, n_epochs=200, biased=True)\n",
    "predict_evaluate(recsys, dataset, 'SVD')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Grid Search Cross Validation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best MAE: 0.18\n",
      "Best RMSE: 0.42\n",
      "Best Params {'p': 0.01}\n"
     ]
    }
   ],
   "source": [
    "from surprise.model_selection import GridSearchCV\n",
    "from surprise.prediction_algorithms.baseline_only import BaselineOnly\n",
    "\n",
    "param_grid = {\n",
    "    'p': [0.01, 0.05, 0.1, 0.15, 0.2, 0.25]\n",
    "}\n",
    "\n",
    "gscv = GridSearchCV(RandomRating, param_grid, measures=['rmse', 'mae'], cv=4, n_jobs=-1)\n",
    "gscv.fit(dataset)\n",
    "\n",
    "print('Best MAE:', gscv.best_score['mae'].round(2))\n",
    "print('Best RMSE:', gscv.best_score['rmse'].round(2))\n",
    "print('Best Params', gscv.best_params['rmse'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best MAE: 0.27\n",
      "Best RMSE: 0.37\n",
      "Best Params {'bsl_options': {'method': 'als', 'n_epochs': 50, 'reg_u': 25, 'reg_i': 10}, 'verbose': False}\n"
     ]
    }
   ],
   "source": [
    "from surprise.model_selection import GridSearchCV\n",
    "from surprise.prediction_algorithms.baseline_only import BaselineOnly\n",
    "\n",
    "param_grid = {\n",
    "    'bsl_options': {\n",
    "        'method':['als'],\n",
    "        'n_epochs': [10, 50, 100],\n",
    "        'reg_u': [5, 15, 25],\n",
    "        'reg_i': [5, 10, 20],\n",
    "        \n",
    "    },\n",
    "    'verbose': [False]\n",
    "}\n",
    "\n",
    "gscv = GridSearchCV(BaselineOnly, param_grid, measures=['rmse', 'mae'], cv=4, n_jobs=-1)\n",
    "gscv.fit(dataset)\n",
    "\n",
    "print('Best MAE:', gscv.best_score['mae'].round(2))\n",
    "print('Best RMSE:', gscv.best_score['rmse'].round(2))\n",
    "print('Best Params', gscv.best_params['rmse'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Estimating biases using als...\n",
      "RMSE: 0.3627\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.3626748465333959"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.baseline_only import BaselineOnly\n",
    "from surprise import accuracy\n",
    "\n",
    "recsys = BaselineOnly()\n",
    "recsys.fit(trainset)\n",
    "predictions = recsys.test(testset)\n",
    "\n",
    "# Then compute RMSE\n",
    "accuracy.rmse(predictions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RMSE: 0.3691\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.3690946254897409"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.matrix_factorization import SVD\n",
    "from surprise import accuracy\n",
    "\n",
    "recsys = SVD(\n",
    "    n_factors=20,\n",
    "    n_epochs=100,\n",
    "    verbose=False,\n",
    ")\n",
    "recsys.fit(trainset)\n",
    "predictions = recsys.test(testset)\n",
    "\n",
    "# Then compute RMSE\n",
    "accuracy.rmse(predictions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Computing the msd similarity matrix...\n",
      "Done computing similarity matrix.\n",
      "RMSE: 0.3741\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.3741212904849874"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.knns import KNNBasic\n",
    "from surprise import accuracy\n",
    "\n",
    "recsys = KNNBasic()\n",
    "recsys.fit(trainset)\n",
    "predictions = recsys.test(testset)\n",
    "\n",
    "# Then compute RMSE\n",
    "accuracy.rmse(predictions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Computing the msd similarity matrix...\n",
      "Done computing similarity matrix.\n",
      "RMSE: 0.3723\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.37231105974057027"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.knns import KNNWithMeans\n",
    "from surprise import accuracy\n",
    "\n",
    "recsys = KNNWithMeans()\n",
    "recsys.fit(trainset)\n",
    "predictions = recsys.test(testset)\n",
    "\n",
    "# Then compute RMSE\n",
    "accuracy.rmse(predictions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Estimating biases using als...\n",
      "Computing the msd similarity matrix...\n",
      "Done computing similarity matrix.\n",
      "RMSE: 0.3670\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.3670470734572328"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from surprise.prediction_algorithms.knns import KNNBaseline\n",
    "from surprise import accuracy\n",
    "\n",
    "recsys = KNNBaseline()\n",
    "recsys.fit(trainset)\n",
    "predictions = recsys.test(testset)\n",
    "\n",
    "# Then compute RMSE\n",
    "accuracy.rmse(predictions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Estimating biases using als...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "['recsys.pkl']"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import joblib\n",
    "from surprise.prediction_algorithms.baseline_only import BaselineOnly\n",
    "\n",
    "recsys = BaselineOnly()\n",
    "recsys.fit(trainset)\n",
    "joblib.dump(recsys, 'recsys.pkl') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RMSE: 0.3627\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "0.3626748465333959"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from surprise import accuracy\n",
    "recsys = joblib.load('recsys.pkl') \n",
    "predictions = recsys.test(testset)\n",
    "accuracy.rmse(predictions)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Music Ratings Example "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "music_ratings = [\n",
    "    ('U1', 'Metallica'), ('U1', 'Rammstein'), ('U2', 'Rammstein'), ('U3', 'Tiesto'), ('U3', 'Paul van Dyk'),\n",
    "    ('U2', 'Metallica'), ('U4', 'Tiesto'), ('U4', 'Paul van Dyk'), ('U5', 'Metallica'),  ('U5', 'Slipknot'),\n",
    "    ('U6', 'Tiesto'), ('U6', 'Aly & Fila'), ('U3', 'Aly & Fila')\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_9566225c_c5d3_11ea_82bc_784f43517922row0_col0 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row0_col1 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row0_col2 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row0_col3 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row0_col4 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row0_col5 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row1_col0 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row1_col1 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row1_col2 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row1_col3 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row1_col4 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row1_col5 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row2_col0 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row2_col1 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row2_col2 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row2_col3 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row2_col4 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row2_col5 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row3_col0 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row3_col1 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row3_col2 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row3_col3 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row3_col4 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row3_col5 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row4_col0 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row4_col1 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row4_col2 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row4_col3 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row4_col4 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row4_col5 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row5_col0 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row5_col1 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row5_col2 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row5_col3 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row5_col4 {\n",
       "            background-color:  black;\n",
       "             color:  white;\n",
       "        }    #T_9566225c_c5d3_11ea_82bc_784f43517922row5_col5 {\n",
       "            background-color:  white;\n",
       "             color:  black;\n",
       "        }</style><table id=\"T_9566225c_c5d3_11ea_82bc_784f43517922\" ><thead>    <tr>        <th class=\"index_name level0\" >Artist</th>        <th class=\"col_heading level0 col0\" >Aly & Fila</th>        <th class=\"col_heading level0 col1\" >Metallica</th>        <th class=\"col_heading level0 col2\" >Paul van Dyk</th>        <th class=\"col_heading level0 col3\" >Rammstein</th>        <th class=\"col_heading level0 col4\" >Slipknot</th>        <th class=\"col_heading level0 col5\" >Tiesto</th>    </tr>    <tr>        <th class=\"index_name level0\" >User</th>        <th class=\"blank\" ></th>        <th class=\"blank\" ></th>        <th class=\"blank\" ></th>        <th class=\"blank\" ></th>        <th class=\"blank\" ></th>        <th class=\"blank\" ></th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_9566225c_c5d3_11ea_82bc_784f43517922level0_row0\" class=\"row_heading level0 row0\" >U1</th>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row0_col0\" class=\"data row0 col0\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row0_col1\" class=\"data row0 col1\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row0_col2\" class=\"data row0 col2\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row0_col3\" class=\"data row0 col3\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row0_col4\" class=\"data row0 col4\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row0_col5\" class=\"data row0 col5\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_9566225c_c5d3_11ea_82bc_784f43517922level0_row1\" class=\"row_heading level0 row1\" >U2</th>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row1_col0\" class=\"data row1 col0\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row1_col1\" class=\"data row1 col1\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row1_col2\" class=\"data row1 col2\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row1_col3\" class=\"data row1 col3\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row1_col4\" class=\"data row1 col4\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row1_col5\" class=\"data row1 col5\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_9566225c_c5d3_11ea_82bc_784f43517922level0_row2\" class=\"row_heading level0 row2\" >U3</th>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row2_col0\" class=\"data row2 col0\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row2_col1\" class=\"data row2 col1\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row2_col2\" class=\"data row2 col2\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row2_col3\" class=\"data row2 col3\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row2_col4\" class=\"data row2 col4\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row2_col5\" class=\"data row2 col5\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_9566225c_c5d3_11ea_82bc_784f43517922level0_row3\" class=\"row_heading level0 row3\" >U4</th>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row3_col0\" class=\"data row3 col0\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row3_col1\" class=\"data row3 col1\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row3_col2\" class=\"data row3 col2\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row3_col3\" class=\"data row3 col3\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row3_col4\" class=\"data row3 col4\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row3_col5\" class=\"data row3 col5\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_9566225c_c5d3_11ea_82bc_784f43517922level0_row4\" class=\"row_heading level0 row4\" >U5</th>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row4_col0\" class=\"data row4 col0\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row4_col1\" class=\"data row4 col1\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row4_col2\" class=\"data row4 col2\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row4_col3\" class=\"data row4 col3\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row4_col4\" class=\"data row4 col4\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row4_col5\" class=\"data row4 col5\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_9566225c_c5d3_11ea_82bc_784f43517922level0_row5\" class=\"row_heading level0 row5\" >U6</th>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row5_col0\" class=\"data row5 col0\" >1</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row5_col1\" class=\"data row5 col1\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row5_col2\" class=\"data row5 col2\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row5_col3\" class=\"data row5 col3\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row5_col4\" class=\"data row5 col4\" >0</td>\n",
       "                        <td id=\"T_9566225c_c5d3_11ea_82bc_784f43517922row5_col5\" class=\"data row5 col5\" >1</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0ef6b6e10>"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_music_ratings = pd.DataFrame(music_ratings, columns=['User', 'Artist'])\n",
    "df_music_ratings['Rating'] = 1\n",
    "\n",
    "df_music_ratings_pivoted = df_music_ratings.pivot('User', 'Artist', 'Rating').fillna(0)\n",
    "\n",
    "df_music_ratings_pivoted.style.applymap(\n",
    "    lambda cell: 'background-color: black; color: white' if cell == 0 else 'background-color: white; color: black'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.  ,  1.37],\n",
       "       [ 0.  ,  1.37],\n",
       "       [ 1.71,  0.  ],\n",
       "       [ 1.21,  0.  ],\n",
       "       [-0.  ,  1.  ],\n",
       "       [ 1.21, -0.  ]])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.decomposition import TruncatedSVD\n",
    "\n",
    "svd = TruncatedSVD(n_components=2)\n",
    "svd.fit_transform(df_music_ratings_pivoted).round(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_95a233dc_c5d3_11ea_9319_784f43517922row0_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row0_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row1_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row1_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row2_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row2_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row3_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 70.8%, transparent 70.8%);\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row3_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row4_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row4_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 73.0%, transparent 73.0%);\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row5_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 70.8%, transparent 70.8%);\n",
       "        }    #T_95a233dc_c5d3_11ea_9319_784f43517922row5_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }</style><table id=\"T_95a233dc_c5d3_11ea_9319_784f43517922\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >SV1</th>        <th class=\"col_heading level0 col1\" >SV2</th>    </tr>    <tr>        <th class=\"index_name level0\" >User</th>        <th class=\"blank\" ></th>        <th class=\"blank\" ></th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_95a233dc_c5d3_11ea_9319_784f43517922level0_row0\" class=\"row_heading level0 row0\" >U1</th>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row0_col0\" class=\"data row0 col0\" >0</td>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row0_col1\" class=\"data row0 col1\" >1.37</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95a233dc_c5d3_11ea_9319_784f43517922level0_row1\" class=\"row_heading level0 row1\" >U2</th>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row1_col0\" class=\"data row1 col0\" >0</td>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row1_col1\" class=\"data row1 col1\" >1.37</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95a233dc_c5d3_11ea_9319_784f43517922level0_row2\" class=\"row_heading level0 row2\" >U3</th>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row2_col0\" class=\"data row2 col0\" >1.71</td>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row2_col1\" class=\"data row2 col1\" >-0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95a233dc_c5d3_11ea_9319_784f43517922level0_row3\" class=\"row_heading level0 row3\" >U4</th>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row3_col0\" class=\"data row3 col0\" >1.21</td>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row3_col1\" class=\"data row3 col1\" >-0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95a233dc_c5d3_11ea_9319_784f43517922level0_row4\" class=\"row_heading level0 row4\" >U5</th>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row4_col0\" class=\"data row4 col0\" >0</td>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row4_col1\" class=\"data row4 col1\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95a233dc_c5d3_11ea_9319_784f43517922level0_row5\" class=\"row_heading level0 row5\" >U6</th>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row5_col0\" class=\"data row5 col0\" >1.21</td>\n",
       "                        <td id=\"T_95a233dc_c5d3_11ea_9319_784f43517922row5_col1\" class=\"data row5 col1\" >-0</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0ecdee320>"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.DataFrame(\n",
    "    svd.fit_transform(df_music_ratings_pivoted),\n",
    "    index=df_music_ratings_pivoted.index,\n",
    "    columns=['SV1', 'SV2'], \n",
    ").round(2).style.bar(\n",
    "    subset=['SV1', 'SV2'],  align='mid', color='#AAA'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_95aa7698_c5d3_11ea_b724_784f43517922row0_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row0_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row0_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row0_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 50.0%, transparent 50.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row1_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row1_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row1_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row1_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 50.0%, transparent 50.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row2_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row2_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row2_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row2_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row3_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 50.0%, transparent 50.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row3_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 50.0%, transparent 50.0%);\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row3_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95aa7698_c5d3_11ea_b724_784f43517922row3_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }</style><table id=\"T_95aa7698_c5d3_11ea_b724_784f43517922\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >U1</th>        <th class=\"col_heading level0 col1\" >U2</th>        <th class=\"col_heading level0 col2\" >U3</th>        <th class=\"col_heading level0 col3\" >U5</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_95aa7698_c5d3_11ea_b724_784f43517922level0_row0\" class=\"row_heading level0 row0\" >U1</th>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row0_col0\" class=\"data row0 col0\" >1</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row0_col1\" class=\"data row0 col1\" >1</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row0_col2\" class=\"data row0 col2\" >0</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row0_col3\" class=\"data row0 col3\" >0.5</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95aa7698_c5d3_11ea_b724_784f43517922level0_row1\" class=\"row_heading level0 row1\" >U2</th>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row1_col0\" class=\"data row1 col0\" >1</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row1_col1\" class=\"data row1 col1\" >1</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row1_col2\" class=\"data row1 col2\" >0</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row1_col3\" class=\"data row1 col3\" >0.5</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95aa7698_c5d3_11ea_b724_784f43517922level0_row2\" class=\"row_heading level0 row2\" >U3</th>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row2_col0\" class=\"data row2 col0\" >0</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row2_col1\" class=\"data row2 col1\" >0</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row2_col2\" class=\"data row2 col2\" >1</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row2_col3\" class=\"data row2 col3\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95aa7698_c5d3_11ea_b724_784f43517922level0_row3\" class=\"row_heading level0 row3\" >U5</th>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row3_col0\" class=\"data row3 col0\" >0.5</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row3_col1\" class=\"data row3 col1\" >0.5</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row3_col2\" class=\"data row3 col2\" >0</td>\n",
       "                        <td id=\"T_95aa7698_c5d3_11ea_b724_784f43517922row3_col3\" class=\"data row3 col3\" >1</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0ee973860>"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics.pairwise import cosine_similarity\n",
    "\n",
    "user_ids = ['U1', 'U2', 'U3', 'U5']\n",
    "\n",
    "pd.DataFrame(\n",
    "    cosine_similarity(\n",
    "        df_music_ratings_pivoted.loc[user_ids, :].values\n",
    "    ),\n",
    "    index=user_ids,\n",
    "    columns=user_ids\n",
    ").round(2).style.bar(\n",
    "    subset=user_ids,  align='mid', color='#AAA'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_95b44554_c5d3_11ea_9b1d_784f43517922row0_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row0_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row0_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row0_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row1_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row1_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row1_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row1_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row2_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row2_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row2_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row2_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row3_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row3_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row3_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95b44554_c5d3_11ea_9b1d_784f43517922row3_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }</style><table id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >U1</th>        <th class=\"col_heading level0 col1\" >U2</th>        <th class=\"col_heading level0 col2\" >U3</th>        <th class=\"col_heading level0 col3\" >U5</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922level0_row0\" class=\"row_heading level0 row0\" >U1</th>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row0_col0\" class=\"data row0 col0\" >1</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row0_col1\" class=\"data row0 col1\" >1</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row0_col2\" class=\"data row0 col2\" >0</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row0_col3\" class=\"data row0 col3\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922level0_row1\" class=\"row_heading level0 row1\" >U2</th>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row1_col0\" class=\"data row1 col0\" >1</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row1_col1\" class=\"data row1 col1\" >1</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row1_col2\" class=\"data row1 col2\" >0</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row1_col3\" class=\"data row1 col3\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922level0_row2\" class=\"row_heading level0 row2\" >U3</th>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row2_col0\" class=\"data row2 col0\" >0</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row2_col1\" class=\"data row2 col1\" >0</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row2_col2\" class=\"data row2 col2\" >1</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row2_col3\" class=\"data row2 col3\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922level0_row3\" class=\"row_heading level0 row3\" >U5</th>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row3_col0\" class=\"data row3 col0\" >1</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row3_col1\" class=\"data row3 col1\" >1</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row3_col2\" class=\"data row3 col2\" >0</td>\n",
       "                        <td id=\"T_95b44554_c5d3_11ea_9b1d_784f43517922row3_col3\" class=\"data row3 col3\" >1</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0ee977358>"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics.pairwise import cosine_similarity\n",
    "\n",
    "user_ids = ['U1', 'U2', 'U3', 'U5']\n",
    "\n",
    "df_user_svd = pd.DataFrame(\n",
    "    svd.fit_transform(df_music_ratings_pivoted),\n",
    "    index=df_music_ratings_pivoted.index,\n",
    "    columns=['SV1', 'SV2'], \n",
    ")\n",
    "\n",
    "pd.DataFrame(\n",
    "    cosine_similarity(\n",
    "        df_user_svd.loc[user_ids, :].values\n",
    "    ),\n",
    "    index=user_ids,\n",
    "    columns=user_ids\n",
    ").round(2).style.bar(\n",
    "    subset=user_ids,  align='mid', color='#AAA'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row0_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row0_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row0_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row0_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row1_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row1_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row1_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row1_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 50.0%, transparent 50.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row2_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row2_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row2_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row2_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row3_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row3_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 50.0%, transparent 50.0%);\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row3_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95bd6258_c5d3_11ea_9c7b_784f43517922row3_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }</style><table id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >U3</th>        <th class=\"col_heading level0 col1\" >U4</th>        <th class=\"col_heading level0 col2\" >U5</th>        <th class=\"col_heading level0 col3\" >U6</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922level0_row0\" class=\"row_heading level0 row0\" >U3</th>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row0_col0\" class=\"data row0 col0\" >1</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row0_col1\" class=\"data row0 col1\" >0.82</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row0_col2\" class=\"data row0 col2\" >0</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row0_col3\" class=\"data row0 col3\" >0.82</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922level0_row1\" class=\"row_heading level0 row1\" >U4</th>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row1_col0\" class=\"data row1 col0\" >0.82</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row1_col1\" class=\"data row1 col1\" >1</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row1_col2\" class=\"data row1 col2\" >0</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row1_col3\" class=\"data row1 col3\" >0.5</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922level0_row2\" class=\"row_heading level0 row2\" >U5</th>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row2_col0\" class=\"data row2 col0\" >0</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row2_col1\" class=\"data row2 col1\" >0</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row2_col2\" class=\"data row2 col2\" >1</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row2_col3\" class=\"data row2 col3\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922level0_row3\" class=\"row_heading level0 row3\" >U6</th>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row3_col0\" class=\"data row3 col0\" >0.82</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row3_col1\" class=\"data row3 col1\" >0.5</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row3_col2\" class=\"data row3 col2\" >0</td>\n",
       "                        <td id=\"T_95bd6258_c5d3_11ea_9c7b_784f43517922row3_col3\" class=\"data row3 col3\" >1</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0ee942eb8>"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics.pairwise import cosine_similarity\n",
    "\n",
    "user_ids = ['U3', 'U4', 'U5', 'U6']\n",
    "\n",
    "pd.DataFrame(\n",
    "    cosine_similarity(\n",
    "        df_music_ratings_pivoted.loc[user_ids, :].values\n",
    "    ),\n",
    "    index=user_ids,\n",
    "    columns=user_ids\n",
    ").round(2).style.bar(\n",
    "    subset=user_ids,  align='mid', color='#AAA'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_95c79174_c5d3_11ea_b235_784f43517922row0_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row0_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row0_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row0_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row1_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row1_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row1_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row1_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row2_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row2_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row2_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row2_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row3_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row3_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row3_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95c79174_c5d3_11ea_b235_784f43517922row3_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }</style><table id=\"T_95c79174_c5d3_11ea_b235_784f43517922\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >U3</th>        <th class=\"col_heading level0 col1\" >U4</th>        <th class=\"col_heading level0 col2\" >U5</th>        <th class=\"col_heading level0 col3\" >U6</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_95c79174_c5d3_11ea_b235_784f43517922level0_row0\" class=\"row_heading level0 row0\" >U3</th>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row0_col0\" class=\"data row0 col0\" >1</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row0_col1\" class=\"data row0 col1\" >1</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row0_col2\" class=\"data row0 col2\" >0</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row0_col3\" class=\"data row0 col3\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95c79174_c5d3_11ea_b235_784f43517922level0_row1\" class=\"row_heading level0 row1\" >U4</th>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row1_col0\" class=\"data row1 col0\" >1</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row1_col1\" class=\"data row1 col1\" >1</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row1_col2\" class=\"data row1 col2\" >-0</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row1_col3\" class=\"data row1 col3\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95c79174_c5d3_11ea_b235_784f43517922level0_row2\" class=\"row_heading level0 row2\" >U5</th>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row2_col0\" class=\"data row2 col0\" >0</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row2_col1\" class=\"data row2 col1\" >-0</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row2_col2\" class=\"data row2 col2\" >1</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row2_col3\" class=\"data row2 col3\" >-0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95c79174_c5d3_11ea_b235_784f43517922level0_row3\" class=\"row_heading level0 row3\" >U6</th>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row3_col0\" class=\"data row3 col0\" >1</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row3_col1\" class=\"data row3 col1\" >1</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row3_col2\" class=\"data row3 col2\" >-0</td>\n",
       "                        <td id=\"T_95c79174_c5d3_11ea_b235_784f43517922row3_col3\" class=\"data row3 col3\" >1</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0ee977208>"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics.pairwise import cosine_similarity\n",
    "\n",
    "user_ids = ['U3', 'U4', 'U5', 'U6']\n",
    "\n",
    "df_user_svd = pd.DataFrame(\n",
    "    svd.fit_transform(df_music_ratings_pivoted),\n",
    "    index=df_music_ratings_pivoted.index,\n",
    "    columns=['Component1', 'Component2'], \n",
    ")\n",
    "\n",
    "pd.DataFrame(\n",
    "    cosine_similarity(\n",
    "        df_user_svd.loc[user_ids, :].values\n",
    "    ),\n",
    "    index=user_ids,\n",
    "    columns=user_ids\n",
    ").round(2).style.bar(\n",
    "    subset=user_ids,  align='mid', color='#AAA'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row0_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 70.4%, transparent 70.4%);\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row0_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row1_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row1_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row2_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 70.4%, transparent 70.4%);\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row2_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row3_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row3_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 73.4%, transparent 73.4%);\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row4_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row4_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 26.6%, transparent 26.6%);\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row5_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95cd95c2_c5d3_11ea_8ab6_784f43517922row5_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }</style><table id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >Component1</th>        <th class=\"col_heading level0 col1\" >Component2</th>    </tr>    <tr>        <th class=\"index_name level0\" >Artist</th>        <th class=\"blank\" ></th>        <th class=\"blank\" ></th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922level0_row0\" class=\"row_heading level0 row0\" >Aly & Fila</th>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row0_col0\" class=\"data row0 col0\" >0.5</td>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row0_col1\" class=\"data row0 col1\" >-0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922level0_row1\" class=\"row_heading level0 row1\" >Metallica</th>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row1_col0\" class=\"data row1 col0\" >-0</td>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row1_col1\" class=\"data row1 col1\" >0.79</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922level0_row2\" class=\"row_heading level0 row2\" >Paul van Dyk</th>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row2_col0\" class=\"data row2 col0\" >0.5</td>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row2_col1\" class=\"data row2 col1\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922level0_row3\" class=\"row_heading level0 row3\" >Rammstein</th>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row3_col0\" class=\"data row3 col0\" >-0</td>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row3_col1\" class=\"data row3 col1\" >0.58</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922level0_row4\" class=\"row_heading level0 row4\" >Slipknot</th>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row4_col0\" class=\"data row4 col0\" >-0</td>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row4_col1\" class=\"data row4 col1\" >0.21</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922level0_row5\" class=\"row_heading level0 row5\" >Tiesto</th>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row5_col0\" class=\"data row5 col0\" >0.71</td>\n",
       "                        <td id=\"T_95cd95c2_c5d3_11ea_8ab6_784f43517922row5_col1\" class=\"data row5 col1\" >-0</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0ee9734a8>"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pd.DataFrame(\n",
    "    svd.components_,\n",
    "    index=['Component1', 'Component2'],\n",
    "    columns=df_music_ratings_pivoted.columns,\n",
    ").T.round(2).style.bar(\n",
    "    subset=['Component1', 'Component2'],  align='mid', color='#AAA'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_95d86346_c5d3_11ea_9426_784f43517922row0_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row0_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row0_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 50.0%, transparent 50.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row0_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row0_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row0_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row1_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row1_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row1_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row1_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row1_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 58.0%, transparent 58.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row1_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row2_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 50.0%, transparent 50.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row2_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row2_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row2_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row2_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row2_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row3_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row3_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row3_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row3_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row3_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row3_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row4_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row4_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 58.0%, transparent 58.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row4_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row4_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row4_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row4_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row5_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row5_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row5_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 82.0%, transparent 82.0%);\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row5_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row5_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95d86346_c5d3_11ea_9426_784f43517922row5_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }</style><table id=\"T_95d86346_c5d3_11ea_9426_784f43517922\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >Aly & Fila</th>        <th class=\"col_heading level0 col1\" >Metallica</th>        <th class=\"col_heading level0 col2\" >Paul van Dyk</th>        <th class=\"col_heading level0 col3\" >Rammstein</th>        <th class=\"col_heading level0 col4\" >Slipknot</th>        <th class=\"col_heading level0 col5\" >Tiesto</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_95d86346_c5d3_11ea_9426_784f43517922level0_row0\" class=\"row_heading level0 row0\" >Aly & Fila</th>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row0_col0\" class=\"data row0 col0\" >1</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row0_col1\" class=\"data row0 col1\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row0_col2\" class=\"data row0 col2\" >0.5</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row0_col3\" class=\"data row0 col3\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row0_col4\" class=\"data row0 col4\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row0_col5\" class=\"data row0 col5\" >0.82</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95d86346_c5d3_11ea_9426_784f43517922level0_row1\" class=\"row_heading level0 row1\" >Metallica</th>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row1_col0\" class=\"data row1 col0\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row1_col1\" class=\"data row1 col1\" >1</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row1_col2\" class=\"data row1 col2\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row1_col3\" class=\"data row1 col3\" >0.82</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row1_col4\" class=\"data row1 col4\" >0.58</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row1_col5\" class=\"data row1 col5\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95d86346_c5d3_11ea_9426_784f43517922level0_row2\" class=\"row_heading level0 row2\" >Paul van Dyk</th>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row2_col0\" class=\"data row2 col0\" >0.5</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row2_col1\" class=\"data row2 col1\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row2_col2\" class=\"data row2 col2\" >1</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row2_col3\" class=\"data row2 col3\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row2_col4\" class=\"data row2 col4\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row2_col5\" class=\"data row2 col5\" >0.82</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95d86346_c5d3_11ea_9426_784f43517922level0_row3\" class=\"row_heading level0 row3\" >Rammstein</th>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row3_col0\" class=\"data row3 col0\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row3_col1\" class=\"data row3 col1\" >0.82</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row3_col2\" class=\"data row3 col2\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row3_col3\" class=\"data row3 col3\" >1</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row3_col4\" class=\"data row3 col4\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row3_col5\" class=\"data row3 col5\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95d86346_c5d3_11ea_9426_784f43517922level0_row4\" class=\"row_heading level0 row4\" >Slipknot</th>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row4_col0\" class=\"data row4 col0\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row4_col1\" class=\"data row4 col1\" >0.58</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row4_col2\" class=\"data row4 col2\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row4_col3\" class=\"data row4 col3\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row4_col4\" class=\"data row4 col4\" >1</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row4_col5\" class=\"data row4 col5\" >0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95d86346_c5d3_11ea_9426_784f43517922level0_row5\" class=\"row_heading level0 row5\" >Tiesto</th>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row5_col0\" class=\"data row5 col0\" >0.82</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row5_col1\" class=\"data row5 col1\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row5_col2\" class=\"data row5 col2\" >0.82</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row5_col3\" class=\"data row5 col3\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row5_col4\" class=\"data row5 col4\" >0</td>\n",
       "                        <td id=\"T_95d86346_c5d3_11ea_9426_784f43517922row5_col5\" class=\"data row5 col5\" >1</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0f413d860>"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics.pairwise import cosine_similarity\n",
    "\n",
    "artist_ids = ['Aly & Fila', 'Metallica', 'Paul van Dyk', 'Rammstein', 'Slipknot', 'Tiesto']\n",
    "\n",
    "pd.DataFrame(\n",
    "    cosine_similarity(\n",
    "        df_music_ratings_pivoted.T.loc[artist_ids, :].values\n",
    "    ),\n",
    "    index=artist_ids,\n",
    "    columns=artist_ids\n",
    ").round(2).style.bar(\n",
    "    subset=artist_ids,  align='mid', color='#AAA'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style  type=\"text/css\" >\n",
       "    #T_95e57070_c5d3_11ea_838a_784f43517922row0_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row0_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row0_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row0_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row0_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row0_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row1_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row1_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row1_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row1_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row1_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row1_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row2_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row2_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row2_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row2_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row2_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row2_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row3_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row3_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row3_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row3_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row3_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row3_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row4_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row4_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row4_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row4_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row4_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row4_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row5_col0 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row5_col1 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row5_col2 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row5_col3 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row5_col4 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "        }    #T_95e57070_c5d3_11ea_838a_784f43517922row5_col5 {\n",
       "            width:  10em;\n",
       "             height:  80%;\n",
       "            background:  linear-gradient(90deg,#AAA 100.0%, transparent 100.0%);\n",
       "        }</style><table id=\"T_95e57070_c5d3_11ea_838a_784f43517922\" ><thead>    <tr>        <th class=\"blank level0\" ></th>        <th class=\"col_heading level0 col0\" >Aly & Fila</th>        <th class=\"col_heading level0 col1\" >Metallica</th>        <th class=\"col_heading level0 col2\" >Paul van Dyk</th>        <th class=\"col_heading level0 col3\" >Rammstein</th>        <th class=\"col_heading level0 col4\" >Slipknot</th>        <th class=\"col_heading level0 col5\" >Tiesto</th>    </tr></thead><tbody>\n",
       "                <tr>\n",
       "                        <th id=\"T_95e57070_c5d3_11ea_838a_784f43517922level0_row0\" class=\"row_heading level0 row0\" >Aly & Fila</th>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row0_col0\" class=\"data row0 col0\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row0_col1\" class=\"data row0 col1\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row0_col2\" class=\"data row0 col2\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row0_col3\" class=\"data row0 col3\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row0_col4\" class=\"data row0 col4\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row0_col5\" class=\"data row0 col5\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95e57070_c5d3_11ea_838a_784f43517922level0_row1\" class=\"row_heading level0 row1\" >Metallica</th>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row1_col0\" class=\"data row1 col0\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row1_col1\" class=\"data row1 col1\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row1_col2\" class=\"data row1 col2\" >0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row1_col3\" class=\"data row1 col3\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row1_col4\" class=\"data row1 col4\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row1_col5\" class=\"data row1 col5\" >-0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95e57070_c5d3_11ea_838a_784f43517922level0_row2\" class=\"row_heading level0 row2\" >Paul van Dyk</th>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row2_col0\" class=\"data row2 col0\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row2_col1\" class=\"data row2 col1\" >0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row2_col2\" class=\"data row2 col2\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row2_col3\" class=\"data row2 col3\" >0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row2_col4\" class=\"data row2 col4\" >0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row2_col5\" class=\"data row2 col5\" >1</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95e57070_c5d3_11ea_838a_784f43517922level0_row3\" class=\"row_heading level0 row3\" >Rammstein</th>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row3_col0\" class=\"data row3 col0\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row3_col1\" class=\"data row3 col1\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row3_col2\" class=\"data row3 col2\" >0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row3_col3\" class=\"data row3 col3\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row3_col4\" class=\"data row3 col4\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row3_col5\" class=\"data row3 col5\" >-0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95e57070_c5d3_11ea_838a_784f43517922level0_row4\" class=\"row_heading level0 row4\" >Slipknot</th>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row4_col0\" class=\"data row4 col0\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row4_col1\" class=\"data row4 col1\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row4_col2\" class=\"data row4 col2\" >0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row4_col3\" class=\"data row4 col3\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row4_col4\" class=\"data row4 col4\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row4_col5\" class=\"data row4 col5\" >-0</td>\n",
       "            </tr>\n",
       "            <tr>\n",
       "                        <th id=\"T_95e57070_c5d3_11ea_838a_784f43517922level0_row5\" class=\"row_heading level0 row5\" >Tiesto</th>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row5_col0\" class=\"data row5 col0\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row5_col1\" class=\"data row5 col1\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row5_col2\" class=\"data row5 col2\" >1</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row5_col3\" class=\"data row5 col3\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row5_col4\" class=\"data row5 col4\" >-0</td>\n",
       "                        <td id=\"T_95e57070_c5d3_11ea_838a_784f43517922row5_col5\" class=\"data row5 col5\" >1</td>\n",
       "            </tr>\n",
       "    </tbody></table>"
      ],
      "text/plain": [
       "<pandas.io.formats.style.Styler at 0x7fd0ee8b6a58>"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.metrics.pairwise import cosine_similarity\n",
    "\n",
    "artist_ids = ['Aly & Fila', 'Metallica', 'Paul van Dyk', 'Rammstein', 'Slipknot', 'Tiesto']\n",
    "\n",
    "df_artist_svd = pd.DataFrame(\n",
    "    svd.components_,\n",
    "    index=['Component1', 'Component2'],\n",
    "    columns=df_music_ratings_pivoted.columns,\n",
    ").T\n",
    "\n",
    "pd.DataFrame(\n",
    "    cosine_similarity(\n",
    "        df_artist_svd.loc[artist_ids, :].values\n",
    "    ),\n",
    "    index=artist_ids,\n",
    "    columns=artist_ids\n",
    ").round(2).style.bar(\n",
    "    subset=artist_ids,  align='mid', color='#AAA'\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "NearestNeighbors(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "                 metric_params=None, n_jobs=None, n_neighbors=2, p=2,\n",
       "                 radius=1.0)"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.neighbors import NearestNeighbors\n",
    "\n",
    "nn = NearestNeighbors(n_neighbors=2)\n",
    "nn.fit(svd.components_.T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0.29289322, 0.5       , 0.5       ]]), array([[5, 2, 0]]))"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nn.kneighbors([[1, 0]], n_neighbors=3, return_distance=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 2])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "nn.kneighbors([[1, 0]], n_neighbors=2, return_distance=False)[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Tiesto', 'Paul van Dyk']"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_music_ratings_pivoted.columns.values[\n",
    "    nn.kneighbors([[1, 0]], n_neighbors=2, return_distance=False)[0]\n",
    "].tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Metallica', 'Rammstein', 'Slipknot']"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.decomposition import TruncatedSVD\n",
    "from sklearn.neighbors import NearestNeighbors\n",
    "\n",
    "class ArtistRecommender:\n",
    "    \n",
    "    def __init__(self):\n",
    "        pass\n",
    "        \n",
    "    def train(self, ratings):\n",
    "        rating_matrix = self.ratings2matrix(ratings)\n",
    "        self.artists = rating_matrix.columns\n",
    "        components = self.calcuate_svd(rating_matrix)\n",
    "        self.nn = self.build_knn(components)\n",
    "        \n",
    "    def ratings2matrix(self, ratings):\n",
    "        df_ratings = pd.DataFrame(ratings, columns=['User', 'Artist'])\n",
    "        df_ratings['Rating'] = 1\n",
    "        return df_ratings.pivot('User', 'Artist', 'Rating').fillna(0)\n",
    "    \n",
    "    def calcuate_svd(self, rating_matrix):\n",
    "        svd = TruncatedSVD(n_components=2)\n",
    "        svd.fit(rating_matrix)\n",
    "        return svd.components_\n",
    "    \n",
    "    def build_knn(self, components):\n",
    "        nn = NearestNeighbors(n_neighbors=2)\n",
    "        nn.fit(svd.components_.T)\n",
    "        return nn\n",
    "    \n",
    "    def predict(self, x, n_neighbors=2):\n",
    "        return self.artists.values[\n",
    "            self.nn.kneighbors([x], n_neighbors=n_neighbors, return_distance=False)[0]\n",
    "        ].tolist()\n",
    "\n",
    "ac = ArtistRecommender()\n",
    "ac.train(music_ratings)\n",
    "ac.predict([0, 1], n_neighbors=3)\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['artist_recommender.pkl']"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import joblib\n",
    "\n",
    "ac = ArtistRecommender()\n",
    "ac.train(music_ratings)\n",
    "joblib.dump(ac, 'artist_recommender.pkl') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Tiesto', 'Paul van Dyk', 'Aly & Fila', 'Slipknot', 'Rammstein']"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ac = joblib.load('artist_recommender.pkl')\n",
    "ac.predict([1, 0], n_neighbors=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
